﻿using System.Collections.Generic;
using UnityEngine;

namespace UnityView
{
    public interface IAdapter
    {
        int GetCount();
        IViewLayout GetConvertView(int index, IViewLayout view);
    }

    // 表格视图，每一行（列）的大小均相等，可支持水平与垂直布局
    public class TableView : AbsAdapterView<IAdapter>
    {
        public TableView() : this(UICanvas.GetInstance())
        {
        }

        public TableView(IViewLayout parent, string name = "Table View") : base(parent, name)
        {
            BounceEnable = true;
        }

        public override void OnAdapterAttached(IAdapter adapter)
        {
            ItemCount = Adapter.GetCount();
            UpdateContentSize();
            Reload();
        }

        public override Orientation Orientation
        {
            get { return base.Orientation; }
            set
            {
                if (Orientation == value) return;
                VisibleItemCount = value == Orientation.Vertical
                    ? Mathf.CeilToInt(Height / TableItemSize)
                    : Mathf.CeilToInt(Width / TableItemSize);
                foreach (var item in ActiveCells)
                {
                    switch (value)
                    {
                        case Orientation.Horizontal:
                            item.View.RectTransform.sizeDelta = new Vector2(TableItemSize, Height);
                            break;
                        case Orientation.Vertical:
                            item.View.RectTransform.sizeDelta = new Vector2(Width, TableItemSize);
                            break;
                    }
                }

                switch (value)
                {
                    case Orientation.Horizontal:
                        ScrollRect.horizontal = true;
                        ScrollRect.vertical = false;
                        break;
                    case Orientation.Vertical:
                        ScrollRect.horizontal = false;
                        ScrollRect.vertical = true;
                        break;
                }

                UpdateVisibleItemCount();
                ContentTransform.anchoredPosition = Vector2.zero;
                Reload();
                base.Orientation = value;
            }
        }

        protected float TableItemSize = Mathf.Min(Screen.width, Screen.height) * 0.125f;

        public float ItemSize
        {
            get { return TableItemSize; }
            set
            {
                TableItemSize = value;
                CacheUpdate();
                Reload();
            }
        }

        public override float Width
        {
            get { return base.Width; }
            protected set
            {
                base.Width = value;
                if (Orientation == Orientation.Horizontal)
                    VisibleItemCount = Mathf.CeilToInt(value / TableItemSize) + 1;
            }
        }

        public override float Height
        {
            get { return base.Height; }
            protected set
            {
                base.Height = value;
                if (Orientation == Orientation.Vertical) VisibleItemCount = Mathf.CeilToInt(value / TableItemSize) + 1;
            }
        }

        public CircleLinkedList<AdapterCellHolder> ActiveCells = new CircleLinkedList<AdapterCellHolder>(1);

        public void CacheUpdate()
        {
            VisibleItemCount = Orientation == Orientation.Vertical
                ? Mathf.CeilToInt(Height / TableItemSize)
                : Mathf.CeilToInt(Width / TableItemSize);
            VisibleItemCount = VisibleItemCount + 1;
            foreach (var item in ActiveCells)
            {
                if (item == null) continue;
                switch (Orientation)
                {
                    case Orientation.Horizontal:
                        item.View.RectTransform.sizeDelta = new Vector2(TableItemSize, Height);
                        break;
                    case Orientation.Vertical:
                        item.View.RectTransform.sizeDelta = new Vector2(Width, TableItemSize);
                        break;
                }
            }
        }

        public override void ScrollToTop(int index = 0)
        {
            ContentTransform.anchoredPosition = Orientation == Orientation.Vertical
                ? new Vector2(0, ItemSize * index)
                : new Vector2(ItemSize * index, 0);
            StartIndex = GetStartIndex();
            Reload();
        }

        // TableView的每个元素大小相等
        public override void UpdateVisibleItemCount()
        {
            switch (Orientation)
            {
                case Orientation.Horizontal:
                    VisibleItemCount = Mathf.FloorToInt(Width / ItemSize) + 2;
                    break;
                case Orientation.Vertical:
                    VisibleItemCount = Mathf.FloorToInt(Height / ItemSize) + 2;
                    break;
            }

            if (StartIndex + VisibleItemCount > ItemCount) VisibleItemCount = ItemCount - StartIndex;
            ActiveCells.Count = VisibleItemCount;
        }

        public override Vector2 GetItemPosition(int index)
        {
            switch (Orientation)
            {
                case Orientation.Horizontal:
                    return new Vector2(index * ItemSize, 0);
                case Orientation.Vertical:
                    return new Vector2(0, -index * ItemSize);
            }

            return Vector2.zero;
        }

        public override int GetItemIndex(Vector2 v)
        {
            v += ContentAnchor;
            float position = Orientation == Orientation.Horizontal ? -v.x : v.y;
            if (position < 0 || ItemCount == 0) return 0;
            var index = Mathf.FloorToInt(position / TableItemSize);
            if (index > ItemCount - 1) index = ItemCount - 1;
            return index;
        }

        protected override int GetStartIndex()
        {
            return
                GetStartIndex(Orientation == Orientation.Vertical
                    ? ContentTransform.anchoredPosition.y
                    : -ContentTransform.anchoredPosition.x);
        }

        protected int GetStartIndex(float position)
        {
            if (position < 0 || ItemCount == 0) return 0;
            var startIndex = Mathf.FloorToInt(position / TableItemSize);
            if (startIndex > ItemCount - 1) startIndex = ItemCount - 1;
            return startIndex;
        }

        // public LinkedList<AdapterCellHolder> ActiveCells = new LinkedList<AdapterCellHolder>();

        public override void Reload()
        {
            // 停止滚动
            ScrollRect.StopMovement();
            if (Adapter == null) return;
            ItemCount = Adapter.GetCount();
            UpdateContentSize();
            StartIndex = GetStartIndex();
            UpdateVisibleItemCount();

            for (int i = 0; i < ActiveCells.Count; i++)
            {
                var cell = ActiveCells.CurrentNode.Value;
                if (cell == null)
                {
                    // cell = CellCache.Get();
                    ActiveCells.CurrentNode.Value = cell;
                }

                ActiveCells.MoveToNext();

                int index = StartIndex + i;
                IViewLayout convertView = Adapter.GetConvertView(index, cell.View);
                convertView.ParentView = ContentView;
                var size = Orientation == Orientation.Horizontal
                    ? new Vector2(ItemSize, Height)
                    : new Vector2(Width, ItemSize);
                cell.Update(convertView, index, GetItemPosition(index), size);
            }
        }

        // 记录上次更新的位置
        protected Vector2 LastRepositionPosition = Vector2.zero;

        public override void LayoutSubviews()
        {

        }

        protected override Vector2 UpdateContentSize()
        {
            switch (Orientation)
            {
                case Orientation.Vertical:
                    ContentTransform.sizeDelta = new Vector2(Width, TableItemSize * ItemCount);
                    break;
                case Orientation.Horizontal:
                    ContentTransform.sizeDelta = new Vector2(TableItemSize * ItemCount, Height);
                    break;
            }

            return ContentTransform.sizeDelta;
        }
    }
}